diff --git a/mlprec/mld_caggr_bld.f90 b/mlprec/mld_caggr_bld.f90 new file mode 100644 index 00000000..41269806 --- /dev/null +++ b/mlprec/mld_caggr_bld.f90 @@ -0,0 +1,153 @@ +!!$ +!!$ +!!$ MLD2P4 version 1.0 +!!$ MultiLevel Domain Decomposition Parallel Preconditioners Package +!!$ based on PSBLAS (Parallel Sparse BLAS version 2.2) +!!$ +!!$ (C) Copyright 2008 +!!$ +!!$ Salvatore Filippone University of Rome Tor Vergata +!!$ Alfredo Buttari University of Rome Tor Vergata +!!$ Pasqua D'Ambra ICAR-CNR, Naples +!!$ Daniela di Serafino Second University of Naples +!!$ +!!$ Redistribution and use in source and binary forms, with or without +!!$ modification, are permitted provided that the following conditions +!!$ are met: +!!$ 1. Redistributions of source code must retain the above copyright +!!$ notice, this list of conditions and the following disclaimer. +!!$ 2. Redistributions in binary form must reproduce the above copyright +!!$ notice, this list of conditions, and the following disclaimer in the +!!$ documentation and/or other materials provided with the distribution. +!!$ 3. The name of the MLD2P4 group or the names of its contributors may +!!$ not be used to endorse or promote products derived from this +!!$ software without specific written permission. +!!$ +!!$ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +!!$ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +!!$ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +!!$ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MLD2P4 GROUP OR ITS CONTRIBUTORS +!!$ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +!!$ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +!!$ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +!!$ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +!!$ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +!!$ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +!!$ POSSIBILITY OF SUCH DAMAGE. +!!$ +!!$ +! File: mld_caggr_bld.f90 +! +! Subroutine: mld_caggr_bld +! Version: complex +! +! This routine builds the preconditioner corresponding to the current +! level of the multilevel preconditioner. The routine first builds the +! (coarse) matrix associated to the current level from the (fine) matrix +! associated to the previous level, then builds the related base preconditioner. +! Note that this routine is only ever called on levels >= 2. +! +! +! Arguments: +! a - type(psb_dspmat_type). +! The sparse matrix structure containing the local part of the +! matrix to be preconditioned. +! desc_a - type(psb_desc_type), input. +! The communication descriptor of a. +! p - type(mld_c_onelev_type), input/output. +! The preconditioner data structure containing the local +! part of the one-level preconditioner to be built. +! info - integer, output. +! Error code. +! +subroutine mld_caggr_bld(a,desc_a,p,info) + + use psb_base_mod + use mld_inner_mod, mld_protect_name => mld_caggr_bld + + implicit none + + ! Arguments + type(psb_cspmat_type), intent(in), target :: a + type(psb_desc_type), intent(in), target :: desc_a + type(mld_c_interlev_prec_type), intent(inout),target :: p + integer, intent(out) :: info + + ! Local variables + type(psb_desc_type) :: desc_ac + type(psb_cspmat_type) :: ac + character(len=20) :: name + integer :: ictxt, np, me, err_act + + name='mld_caggr_bld' + if (psb_get_errstatus().ne.0) return + call psb_erractionsave(err_act) + info = 0 + ictxt = psb_cd_get_context(desc_a) + call psb_info(ictxt,me,np) + + if (.not.allocated(p%iprcparm)) then + info = 2222 + call psb_errpush(info,name) + goto 9999 + endif + call mld_check_def(p%iprcparm(mld_ml_type_),'Multilevel type',& + & mld_mult_ml_,is_legal_ml_type) + call mld_check_def(p%iprcparm(mld_aggr_alg_),'Aggregation',& + & mld_dec_aggr_,is_legal_ml_aggr_alg) + call mld_check_def(p%iprcparm(mld_aggr_kind_),'Smoother',& + & mld_smooth_prol_,is_legal_ml_aggr_kind) + call mld_check_def(p%iprcparm(mld_coarse_mat_),'Coarse matrix',& + & mld_distr_mat_,is_legal_ml_coarse_mat) + call mld_check_def(p%iprcparm(mld_smoother_pos_),'smooth_pos',& + & mld_pre_smooth_,is_legal_ml_smooth_pos) + call mld_check_def(p%iprcparm(mld_aggr_omega_alg_),'Omega Alg.',& + & mld_eig_est_,is_legal_ml_aggr_omega_alg) + call mld_check_def(p%iprcparm(mld_aggr_eig_),'Eigenvalue estimate',& + & mld_max_norm_,is_legal_ml_aggr_eig) + call mld_check_def(p%rprcparm(mld_aggr_omega_val_),'Omega',szero,is_legal_s_omega) + call mld_check_def(p%rprcparm(mld_aggr_thresh_),'Aggr_Thresh',szero,is_legal_s_aggr_thrs) + + + ! + ! Build a mapping between the row indices of the fine-level matrix + ! and the row indices of the coarse-level matrix, according to a decoupled + ! aggregation algorithm. This also defines a tentative prolongator from + ! the coarse to the fine level. + ! + call mld_aggrmap_bld(p%iprcparm(mld_aggr_alg_),p%rprcparm(mld_aggr_thresh_),& + & a,desc_a,p%nlaggr,p%mlia,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmap_bld') + goto 9999 + end if + + ! + ! Build the coarse-level matrix from the fine level one, starting from + ! the mapping defined by mld_aggrmap_bld and applying the aggregation + ! algorithm specified by p%iprcparm(mld_aggr_kind_) + ! + call mld_aggrmat_asb(a,desc_a,p,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmat_asb') + goto 9999 + end if + ! + ! Fix the base_a and base_desc pointers for handling of residuals. + ! This is correct because this routine is only called at levels >=2. + ! + p%base_a => p%ac + p%base_desc => p%desc_ac + + call psb_erractionrestore(err_act) + return + +9999 continue + call psb_erractionrestore(err_act) + if (err_act.eq.psb_act_abort_) then + call psb_error() + return + end if + Return + +end subroutine mld_caggr_bld diff --git a/mlprec/mld_daggr_bld.f90 b/mlprec/mld_daggr_bld.f90 new file mode 100644 index 00000000..3398ff0a --- /dev/null +++ b/mlprec/mld_daggr_bld.f90 @@ -0,0 +1,153 @@ +!!$ +!!$ +!!$ MLD2P4 version 1.0 +!!$ MultiLevel Domain Decomposition Parallel Preconditioners Package +!!$ based on PSBLAS (Parallel Sparse BLAS version 2.2) +!!$ +!!$ (C) Copyright 2008 +!!$ +!!$ Salvatore Filippone University of Rome Tor Vergata +!!$ Alfredo Buttari University of Rome Tor Vergata +!!$ Pasqua D'Ambra ICAR-CNR, Naples +!!$ Daniela di Serafino Second University of Naples +!!$ +!!$ Redistribution and use in source and binary forms, with or without +!!$ modification, are permitted provided that the following conditions +!!$ are met: +!!$ 1. Redistributions of source code must retain the above copyright +!!$ notice, this list of conditions and the following disclaimer. +!!$ 2. Redistributions in binary form must reproduce the above copyright +!!$ notice, this list of conditions, and the following disclaimer in the +!!$ documentation and/or other materials provided with the distribution. +!!$ 3. The name of the MLD2P4 group or the names of its contributors may +!!$ not be used to endorse or promote products derived from this +!!$ software without specific written permission. +!!$ +!!$ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +!!$ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +!!$ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +!!$ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MLD2P4 GROUP OR ITS CONTRIBUTORS +!!$ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +!!$ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +!!$ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +!!$ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +!!$ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +!!$ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +!!$ POSSIBILITY OF SUCH DAMAGE. +!!$ +!!$ +! File: mld_daggr_bld.f90 +! +! Subroutine: mld_daggr_bld +! Version: real +! +! This routine builds the preconditioner corresponding to the current +! level of the multilevel preconditioner. The routine first builds the +! (coarse) matrix associated to the current level from the (fine) matrix +! associated to the previous level, then builds the related base preconditioner. +! Note that this routine is only ever called on levels >= 2. +! +! +! Arguments: +! a - type(psb_dspmat_type). +! The sparse matrix structure containing the local part of the +! matrix to be preconditioned. +! desc_a - type(psb_desc_type), input. +! The communication descriptor of a. +! p - type(mld_d_onelev_type), input/output. +! The preconditioner data structure containing the local +! part of the one-level preconditioner to be built. +! info - integer, output. +! Error code. +! +subroutine mld_daggr_bld(a,desc_a,p,info) + + use psb_base_mod + use mld_inner_mod, mld_protect_name => mld_daggr_bld + + implicit none + + ! Arguments + type(psb_dspmat_type), intent(in), target :: a + type(psb_desc_type), intent(in), target :: desc_a + type(mld_d_interlev_prec_type), intent(inout),target :: p + integer, intent(out) :: info + + ! Local variables + type(psb_desc_type) :: desc_ac + type(psb_dspmat_type) :: ac + character(len=20) :: name + integer :: ictxt, np, me, err_act + + name='mld_daggr_bld' + if (psb_get_errstatus().ne.0) return + call psb_erractionsave(err_act) + info = 0 + ictxt = psb_cd_get_context(desc_a) + call psb_info(ictxt,me,np) + + if (.not.allocated(p%iprcparm)) then + info = 2222 + call psb_errpush(info,name) + goto 9999 + endif + call mld_check_def(p%iprcparm(mld_ml_type_),'Multilevel type',& + & mld_mult_ml_,is_legal_ml_type) + call mld_check_def(p%iprcparm(mld_aggr_alg_),'Aggregation',& + & mld_dec_aggr_,is_legal_ml_aggr_alg) + call mld_check_def(p%iprcparm(mld_aggr_kind_),'Smoother',& + & mld_smooth_prol_,is_legal_ml_aggr_kind) + call mld_check_def(p%iprcparm(mld_coarse_mat_),'Coarse matrix',& + & mld_distr_mat_,is_legal_ml_coarse_mat) + call mld_check_def(p%iprcparm(mld_smoother_pos_),'smooth_pos',& + & mld_pre_smooth_,is_legal_ml_smooth_pos) + call mld_check_def(p%iprcparm(mld_aggr_omega_alg_),'Omega Alg.',& + & mld_eig_est_,is_legal_ml_aggr_omega_alg) + call mld_check_def(p%iprcparm(mld_aggr_eig_),'Eigenvalue estimate',& + & mld_max_norm_,is_legal_ml_aggr_eig) + call mld_check_def(p%rprcparm(mld_aggr_omega_val_),'Omega',dzero,is_legal_omega) + call mld_check_def(p%rprcparm(mld_aggr_thresh_),'Aggr_Thresh',dzero,is_legal_aggr_thrs) + + + ! + ! Build a mapping between the row indices of the fine-level matrix + ! and the row indices of the coarse-level matrix, according to a decoupled + ! aggregation algorithm. This also defines a tentative prolongator from + ! the coarse to the fine level. + ! + call mld_aggrmap_bld(p%iprcparm(mld_aggr_alg_),p%rprcparm(mld_aggr_thresh_),& + & a,desc_a,p%nlaggr,p%mlia,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmap_bld') + goto 9999 + end if + + ! + ! Build the coarse-level matrix from the fine level one, starting from + ! the mapping defined by mld_aggrmap_bld and applying the aggregation + ! algorithm specified by p%iprcparm(mld_aggr_kind_) + ! + call mld_aggrmat_asb(a,desc_a,p,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmat_asb') + goto 9999 + end if + ! + ! Fix the base_a and base_desc pointers for handling of residuals. + ! This is correct because this routine is only called at levels >=2. + ! + p%base_a => p%ac + p%base_desc => p%desc_ac + + call psb_erractionrestore(err_act) + return + +9999 continue + call psb_erractionrestore(err_act) + if (err_act.eq.psb_act_abort_) then + call psb_error() + return + end if + Return + +end subroutine mld_daggr_bld diff --git a/mlprec/mld_saggr_bld.f90 b/mlprec/mld_saggr_bld.f90 new file mode 100644 index 00000000..942f4b97 --- /dev/null +++ b/mlprec/mld_saggr_bld.f90 @@ -0,0 +1,148 @@ +!!$ +!!$ +!!$ MLD2P4 version 1.0 +!!$ MultiLevel Domain Decomposition Parallel Preconditioners Package +!!$ based on PSBLAS (Parallel Sparse BLAS version 2.2) +!!$ +!!$ (C) Copyright 2008 +!!$ +!!$ Salvatore Filippone University of Rome Tor Vergata +!!$ Alfredo Buttari University of Rome Tor Vergata +!!$ Pasqua D'Ambra ICAR-CNR, Naples +!!$ Daniela di Serafino Second University of Naples +!!$ +!!$ Redistribution and use in source and binary forms, with or without +!!$ modification, are permitted provided that the following conditions +!!$ are met: +!!$ 1. Redistributions of source code must retain the above copyright +!!$ notice, this list of conditions and the following disclaimer. +!!$ 2. Redistributions in binary form must reproduce the above copyright +!!$ notice, this list of conditions, and the following disclaimer in the +!!$ documentation and/or other materials provided with the distribution. +!!$ 3. The name of the MLD2P4 group or the names of its contributors may +!!$ not be used to endorse or promote products derived from this +!!$ software without specific written permission. +!!$ +!!$ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +!!$ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +!!$ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +!!$ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MLD2P4 GROUP OR ITS CONTRIBUTORS +!!$ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +!!$ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +!!$ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +!!$ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +!!$ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +!!$ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +!!$ POSSIBILITY OF SUCH DAMAGE. +!!$ +!!$ +! File: mld_saggr_bld.f90 +! +! Subroutine: mld_saggr_bld +! Version: real +! +! This routine builds the preconditioner corresponding to the current +! level of the multilevel preconditioner. The routine first builds the +! (coarse) matrix associated to the current level from the (fine) matrix +! associated to the previous level, then builds the related base preconditioner. +! Note that this routine is only ever called on levels >= 2. +! +! +! Arguments: +! p - type(mld_s_onelev_type), input/output. +! The preconditioner data structure containing the local +! part of the one-level preconditioner to be built. +! info - integer, output. +! Error code. +! +subroutine mld_saggr_bld(a,desc_a,p,info) + + use psb_base_mod + use mld_inner_mod, mld_protect_name => mld_saggr_bld + + implicit none + + ! Arguments + type(psb_sspmat_type), intent(in), target :: a + type(psb_desc_type), intent(in), target :: desc_a + type(mld_s_interlev_prec_type), intent(inout),target :: p + integer, intent(out) :: info + + ! Local variables + type(psb_desc_type) :: desc_ac + type(psb_sspmat_type) :: ac + character(len=20) :: name + integer :: ictxt, np, me, err_act + + name='mld_saggr_bld' + if (psb_get_errstatus().ne.0) return + call psb_erractionsave(err_act) + info = 0 + ictxt = psb_cd_get_context(desc_a) + call psb_info(ictxt,me,np) + + if (.not.allocated(p%iprcparm)) then + info = 2222 + call psb_errpush(info,name) + goto 9999 + endif + call mld_check_def(p%iprcparm(mld_ml_type_),'Multilevel type',& + & mld_mult_ml_,is_legal_ml_type) + call mld_check_def(p%iprcparm(mld_aggr_alg_),'Aggregation',& + & mld_dec_aggr_,is_legal_ml_aggr_alg) + call mld_check_def(p%iprcparm(mld_aggr_kind_),'Smoother',& + & mld_smooth_prol_,is_legal_ml_aggr_kind) + call mld_check_def(p%iprcparm(mld_coarse_mat_),'Coarse matrix',& + & mld_distr_mat_,is_legal_ml_coarse_mat) + call mld_check_def(p%iprcparm(mld_smoother_pos_),'smooth_pos',& + & mld_pre_smooth_,is_legal_ml_smooth_pos) + call mld_check_def(p%iprcparm(mld_aggr_omega_alg_),'Omega Alg.',& + & mld_eig_est_,is_legal_ml_aggr_omega_alg) + call mld_check_def(p%iprcparm(mld_aggr_eig_),'Eigenvalue estimate',& + & mld_max_norm_,is_legal_ml_aggr_eig) + call mld_check_def(p%rprcparm(mld_aggr_omega_val_),'Omega',szero,is_legal_s_omega) + call mld_check_def(p%rprcparm(mld_aggr_thresh_),'Aggr_Thresh',szero,is_legal_s_aggr_thrs) + + + ! + ! Build a mapping between the row indices of the fine-level matrix + ! and the row indices of the coarse-level matrix, according to a decoupled + ! aggregation algorithm. This also defines a tentative prolongator from + ! the coarse to the fine level. + ! + call mld_aggrmap_bld(p%iprcparm(mld_aggr_alg_),p%rprcparm(mld_aggr_thresh_),& + & a,desc_a,p%nlaggr,p%mlia,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmap_bld') + goto 9999 + end if + + ! + ! Build the coarse-level matrix from the fine level one, starting from + ! the mapping defined by mld_aggrmap_bld and applying the aggregation + ! algorithm specified by p%iprcparm(mld_aggr_kind_) + ! + call mld_aggrmat_asb(a,desc_a,p,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmat_asb') + goto 9999 + end if + ! + ! Fix the base_a and base_desc pointers for handling of residuals. + ! This is correct because this routine is only called at levels >=2. + ! + p%base_a => p%ac + p%base_desc => p%desc_ac + + call psb_erractionrestore(err_act) + return + +9999 continue + call psb_erractionrestore(err_act) + if (err_act.eq.psb_act_abort_) then + call psb_error() + return + end if + Return + +end subroutine mld_saggr_bld diff --git a/mlprec/mld_transfer_mod.F90 b/mlprec/mld_transfer_mod.F90 new file mode 100644 index 00000000..ec6c2f48 --- /dev/null +++ b/mlprec/mld_transfer_mod.F90 @@ -0,0 +1,453 @@ +!!$ +!!$ +!!$ MLD2P4 version 1.0 +!!$ MultiLevel Domain Decomposition Parallel Preconditioners Package +!!$ based on PSBLAS (Parallel Sparse BLAS version 2.2) +!!$ +!!$ (C) Copyright 2008 +!!$ +!!$ Salvatore Filippone University of Rome Tor Vergata +!!$ Alfredo Buttari University of Rome Tor Vergata +!!$ Pasqua D'Ambra ICAR-CNR, Naples +!!$ Daniela di Serafino Second University of Naples +!!$ +!!$ Redistribution and use in source and binary forms, with or without +!!$ modification, are permitted provided that the following conditions +!!$ are met: +!!$ 1. Redistributions of source code must retain the above copyright +!!$ notice, this list of conditions and the following disclaimer. +!!$ 2. Redistributions in binary form must reproduce the above copyright +!!$ notice, this list of conditions, and the following disclaimer in the +!!$ documentation and/or other materials provided with the distribution. +!!$ 3. The name of the MLD2P4 group or the names of its contributors may +!!$ not be used to endorse or promote products derived from this +!!$ software without specific written permission. +!!$ +!!$ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +!!$ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +!!$ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +!!$ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MLD2P4 GROUP OR ITS CONTRIBUTORS +!!$ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +!!$ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +!!$ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +!!$ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +!!$ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +!!$ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +!!$ POSSIBILITY OF SUCH DAMAGE. +!!$ +!!$ +! File: mld_transfer_mod.f90 +! +! Package: mld_prec_type +! Data structure(s) for sparse matrices +! +! This module defines: +! - the mld_prec_type data structure containing the preconditioner; +! - character constants describing the preconditioner, used by the routine +! printing out a preconditioner description; +! - the interfaces to the routines for the management of the preconditioner +! data structure (see below). +! +! It contains: +! - mld_dprec_sizeof, mld_dbaseprc_sizeof, mld_out_prec_descr, mld_file_prec_descr, +! mld_icheck_def, mld_dcheck_def, mld_dbase_precfree, mld_nullify_dbaseprec, +! is_legal_..._..., and their complex versions (if applicable). +! These routines check if the preconditioner is correctly defined, print a +! description of the preconditioner, and deallocate its data structure. +! + +module mld_transfer_mod + + use mld_prec_type + + interface mld_transfer + module procedure mld_sbaseprec_transfer, mld_sonelev_prec_transfer,& + & mld_sprec_transfer,& + & mld_dbaseprec_transfer, mld_donelev_prec_transfer,& + & mld_dprec_transfer,& + & mld_cbaseprec_transfer, mld_conelev_prec_transfer,& + & mld_cprec_transfer,& + & mld_zbaseprec_transfer, mld_zonelev_prec_transfer,& + & mld_zprec_transfer + end interface + +contains + + + subroutine mld_sbaseprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_sbaseprc_type), intent(inout) :: a, b + integer, intent(out) :: info + integer :: i, isz + + call mld_precfree(b,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%desc_data,b%desc_data,info) + if (info == 0) call psb_transfer(a%perm,b%perm,info) + if (info == 0) call psb_transfer(a%invperm,b%invperm,info) +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%av,b%av) +#else + if (allocated(a%av)) then + isz = size(a%av) + allocate(b%av(isz),stat=info) + do i=1,isz + if (info == 0) call psb_transfer(a%av(i), b%av(i), info) + end do + + if (info == 0) deallocate(a%av,stat=info) + end if +#endif + if (info /= 0) then + write(0,*) 'Error in baseprec_:transfer',info + end if + + end subroutine mld_sbaseprec_transfer + + subroutine mld_sonelev_prec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_s_interlev_prec_type), intent(inout) :: a, b + integer, intent(out) :: info + + call mld_precfree(b,info) + if (info == 0) call mld_transfer(a%prec,b%prec,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%ac,b%ac,info) + if (info == 0) call psb_transfer(a%desc_ac,b%desc_ac,info) + if (info == 0) call psb_transfer(a%mlia,b%mlia,info) + if (info == 0) call psb_transfer(a%nlaggr,b%nlaggr,info) + if (info == 0) call psb_transfer(a%map_desc,b%map_desc,info) + b%base_a => a%base_a + b%base_desc => a%base_desc + + end subroutine mld_sonelev_prec_transfer + + subroutine mld_sprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_sprec_type), intent(inout) :: a + type(mld_sprec_type), intent(inout), target :: b + integer, intent(out) :: info + integer :: i,isz + + if (allocated(b%precv)) then + ! This might not be required if FINAL procedures are available. + call mld_precfree(b,info) + if (info /= 0) then + ! ????? + !!$ return + endif + end if + +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%precv,b%precv) +#else + if (.not.allocated(a%precv)) return + isz = size(a%precv) + allocate(b%precv(isz),stat=info) + if (info /= 0) then + write(0,*) 'Memory allocation failure in prec_transfer' + return + end if + do i=1,isz + call mld_transfer(a%precv(i),b%precv(i),info) + end do + deallocate(a%precv,stat=info) +#endif + ! Fix the pointers except on level 1. + do i=2, isz + b%precv(i)%base_a => b%precv(i)%ac + b%precv(i)%base_desc => b%precv(i)%desc_ac + b%precv(i)%map_desc%p_desc_fw => b%precv(i-1)%base_desc + b%precv(i)%map_desc%p_desc_bk => b%precv(i)%base_desc + end do + end subroutine mld_sprec_transfer + + + subroutine mld_dbaseprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_dbaseprc_type), intent(inout) :: a, b + integer, intent(out) :: info + integer :: i, isz + + call mld_precfree(b,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%desc_data,b%desc_data,info) + if (info == 0) call psb_transfer(a%perm,b%perm,info) + if (info == 0) call psb_transfer(a%invperm,b%invperm,info) +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%av,b%av) +#else + if (allocated(a%av)) then + isz = size(a%av) + allocate(b%av(isz),stat=info) + do i=1,isz + if (info == 0) call psb_transfer(a%av(i), b%av(i), info) + end do + + if (info == 0) deallocate(a%av,stat=info) + end if +#endif + if (info /= 0) then + write(0,*) 'Error in baseprec_:transfer',info + end if + + end subroutine mld_dbaseprec_transfer + + subroutine mld_donelev_prec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_d_interlev_prec_type), intent(inout) :: a, b + integer, intent(out) :: info + + call mld_precfree(b,info) + if (info == 0) call mld_transfer(a%prec,b%prec,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%ac,b%ac,info) + if (info == 0) call psb_transfer(a%desc_ac,b%desc_ac,info) + if (info == 0) call psb_transfer(a%mlia,b%mlia,info) + if (info == 0) call psb_transfer(a%nlaggr,b%nlaggr,info) + if (info == 0) call psb_transfer(a%map_desc,b%map_desc,info) + b%base_a => a%base_a + b%base_desc => a%base_desc + + end subroutine mld_donelev_prec_transfer + + subroutine mld_dprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_dprec_type), intent(inout) :: a + type(mld_dprec_type), intent(inout), target :: b + integer, intent(out) :: info + integer :: i,isz + + if (allocated(b%precv)) then + ! This might not be required if FINAL procedures are available. + call mld_precfree(b,info) + if (info /= 0) then + ! ????? + !!$ return + endif + end if + +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%precv,b%precv) +#else + if (.not.allocated(a%precv)) return + isz = size(a%precv) + allocate(b%precv(isz),stat=info) + if (info /= 0) then + write(0,*) 'Memory allocation failure in prec_transfer' + return + end if + do i=1,isz + call mld_transfer(a%precv(i),b%precv(i),info) + end do + deallocate(a%precv,stat=info) +#endif + ! Fix the pointers except on level 1. + do i=2, isz + b%precv(i)%base_a => b%precv(i)%ac + b%precv(i)%base_desc => b%precv(i)%desc_ac + b%precv(i)%map_desc%p_desc_fw => b%precv(i-1)%base_desc + b%precv(i)%map_desc%p_desc_bk => b%precv(i)%base_desc + end do + end subroutine mld_dprec_transfer + + + subroutine mld_cbaseprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_cbaseprc_type), intent(inout) :: a, b + integer, intent(out) :: info + integer :: i, isz + + call mld_precfree(b,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%desc_data,b%desc_data,info) + if (info == 0) call psb_transfer(a%perm,b%perm,info) + if (info == 0) call psb_transfer(a%invperm,b%invperm,info) +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%av,b%av) +#else + if (allocated(a%av)) then + isz = size(a%av) + allocate(b%av(isz),stat=info) + do i=1,isz + if (info == 0) call psb_transfer(a%av(i), b%av(i), info) + end do + + if (info == 0) deallocate(a%av,stat=info) + end if +#endif + if (info /= 0) then + write(0,*) 'Error in baseprec_:transfer',info + end if + + end subroutine mld_cbaseprec_transfer + + subroutine mld_conelev_prec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_c_interlev_prec_type), intent(inout) :: a, b + integer, intent(out) :: info + + call mld_precfree(b,info) + if (info == 0) call mld_transfer(a%prec,b%prec,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%ac,b%ac,info) + if (info == 0) call psb_transfer(a%desc_ac,b%desc_ac,info) + if (info == 0) call psb_transfer(a%mlia,b%mlia,info) + if (info == 0) call psb_transfer(a%nlaggr,b%nlaggr,info) + if (info == 0) call psb_transfer(a%map_desc,b%map_desc,info) + b%base_a => a%base_a + b%base_desc => a%base_desc + + end subroutine mld_conelev_prec_transfer + + subroutine mld_cprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_cprec_type), intent(inout) :: a + type(mld_cprec_type), intent(inout), target :: b + integer, intent(out) :: info + integer :: i,isz + + if (allocated(b%precv)) then + ! This might not be required if FINAL procedures are available. + call mld_precfree(b,info) + if (info /= 0) then + ! ????? + !!$ return + endif + end if + +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%precv,b%precv) +#else + if (.not.allocated(a%precv)) return + isz = size(a%precv) + allocate(b%precv(isz),stat=info) + if (info /= 0) then + write(0,*) 'Memory allocation failure in prec_transfer' + return + end if + do i=1,isz + call mld_transfer(a%precv(i),b%precv(i),info) + end do + deallocate(a%precv,stat=info) +#endif + ! Fix the pointers except on level 1. + do i=2, isz + b%precv(i)%base_a => b%precv(i)%ac + b%precv(i)%base_desc => b%precv(i)%desc_ac + b%precv(i)%map_desc%p_desc_fw => b%precv(i-1)%base_desc + b%precv(i)%map_desc%p_desc_bk => b%precv(i)%base_desc + end do + end subroutine mld_cprec_transfer + + + subroutine mld_zbaseprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_zbaseprc_type), intent(inout) :: a, b + integer, intent(out) :: info + integer :: i, isz + + call mld_precfree(b,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%desc_data,b%desc_data,info) + if (info == 0) call psb_transfer(a%perm,b%perm,info) + if (info == 0) call psb_transfer(a%invperm,b%invperm,info) +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%av,b%av) +#else + if (allocated(a%av)) then + isz = size(a%av) + allocate(b%av(isz),stat=info) + do i=1,isz + if (info == 0) call psb_transfer(a%av(i), b%av(i), info) + end do + + if (info == 0) deallocate(a%av,stat=info) + end if +#endif + if (info /= 0) then + write(0,*) 'Error in baseprec_:transfer',info + end if + + end subroutine mld_zbaseprec_transfer + + subroutine mld_zonelev_prec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_z_interlev_prec_type), intent(inout) :: a, b + integer, intent(out) :: info + + call mld_precfree(b,info) + if (info == 0) call mld_transfer(a%prec,b%prec,info) + if (info == 0) call psb_transfer(a%iprcparm,b%iprcparm,info) + if (info == 0) call psb_transfer(a%rprcparm,b%rprcparm,info) + if (info == 0) call psb_transfer(a%ac,b%ac,info) + if (info == 0) call psb_transfer(a%desc_ac,b%desc_ac,info) + if (info == 0) call psb_transfer(a%mlia,b%mlia,info) + if (info == 0) call psb_transfer(a%nlaggr,b%nlaggr,info) + if (info == 0) call psb_transfer(a%map_desc,b%map_desc,info) + b%base_a => a%base_a + b%base_desc => a%base_desc + + end subroutine mld_zonelev_prec_transfer + + subroutine mld_zprec_transfer(a, b,info) + use psb_base_mod + implicit none + type(mld_zprec_type), intent(inout) :: a + type(mld_zprec_type), intent(inout), target :: b + integer, intent(out) :: info + integer :: i,isz + + if (allocated(b%precv)) then + ! This might not be required if FINAL procedures are available. + call mld_precfree(b,info) + if (info /= 0) then + ! ????? + !!$ return + endif + end if + +#ifdef HAVE_MOVE_ALLOC + call move_alloc(a%precv,b%precv) +#else + if (.not.allocated(a%precv)) return + isz = size(a%precv) + allocate(b%precv(isz),stat=info) + if (info /= 0) then + write(0,*) 'Memory allocation failure in prec_transfer' + return + end if + do i=1,isz + call mld_transfer(a%precv(i),b%precv(i),info) + end do + deallocate(a%precv,stat=info) +#endif + ! Fix the pointers except on level 1. + do i=2, isz + b%precv(i)%base_a => b%precv(i)%ac + b%precv(i)%base_desc => b%precv(i)%desc_ac + b%precv(i)%map_desc%p_desc_fw => b%precv(i-1)%base_desc + b%precv(i)%map_desc%p_desc_bk => b%precv(i)%base_desc + end do + end subroutine mld_zprec_transfer + + +end module mld_transfer_mod diff --git a/mlprec/mld_zaggr_bld.f90 b/mlprec/mld_zaggr_bld.f90 new file mode 100644 index 00000000..172754ea --- /dev/null +++ b/mlprec/mld_zaggr_bld.f90 @@ -0,0 +1,153 @@ +!!$ +!!$ +!!$ MLD2P4 version 1.0 +!!$ MultiLevel Domain Decomposition Parallel Preconditioners Package +!!$ based on PSBLAS (Parallel Sparse BLAS version 2.2) +!!$ +!!$ (C) Copyright 2008 +!!$ +!!$ Salvatore Filippone University of Rome Tor Vergata +!!$ Alfredo Buttari University of Rome Tor Vergata +!!$ Pasqua D'Ambra ICAR-CNR, Naples +!!$ Daniela di Serafino Second University of Naples +!!$ +!!$ Redistribution and use in source and binary forms, with or without +!!$ modification, are permitted provided that the following conditions +!!$ are met: +!!$ 1. Redistributions of source code must retain the above copyright +!!$ notice, this list of conditions and the following disclaimer. +!!$ 2. Redistributions in binary form must reproduce the above copyright +!!$ notice, this list of conditions, and the following disclaimer in the +!!$ documentation and/or other materials provided with the distribution. +!!$ 3. The name of the MLD2P4 group or the names of its contributors may +!!$ not be used to endorse or promote products derived from this +!!$ software without specific written permission. +!!$ +!!$ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +!!$ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +!!$ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +!!$ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE MLD2P4 GROUP OR ITS CONTRIBUTORS +!!$ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +!!$ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +!!$ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +!!$ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +!!$ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +!!$ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +!!$ POSSIBILITY OF SUCH DAMAGE. +!!$ +!!$ +! File: mld_zaggr_bld.f90 +! +! Subroutine: mld_zaggr_bld +! Version: complex +! +! This routine builds the preconditioner corresponding to the current +! level of the multilevel preconditioner. The routine first builds the +! (coarse) matrix associated to the current level from the (fine) matrix +! associated to the previous level, then builds the related base preconditioner. +! Note that this routine is only ever called on levels >= 2. +! +! +! Arguments: +! a - type(psb_dspmat_type). +! The sparse matrix structure containing the local part of the +! matrix to be preconditioned. +! desc_a - type(psb_desc_type), input. +! The communication descriptor of a. +! p - type(mld_z_onelev_type), input/output. +! The preconditioner data structure containing the local +! part of the one-level preconditioner to be built. +! info - integer, output. +! Error code. +! +subroutine mld_zaggr_bld(a,desc_a,p,info) + + use psb_base_mod + use mld_inner_mod, mld_protect_name => mld_zaggr_bld + + implicit none + + ! Arguments + type(psb_zspmat_type), intent(in), target :: a + type(psb_desc_type), intent(in), target :: desc_a + type(mld_z_interlev_prec_type), intent(inout),target :: p + integer, intent(out) :: info + + ! Local variables + type(psb_desc_type) :: desc_ac + type(psb_zspmat_type) :: ac + character(len=20) :: name + integer :: ictxt, np, me, err_act + + name='mld_zaggr_bld' + if (psb_get_errstatus().ne.0) return + call psb_erractionsave(err_act) + info = 0 + ictxt = psb_cd_get_context(desc_a) + call psb_info(ictxt,me,np) + + if (.not.allocated(p%iprcparm)) then + info = 2222 + call psb_errpush(info,name) + goto 9999 + endif + call mld_check_def(p%iprcparm(mld_ml_type_),'Multilevel type',& + & mld_mult_ml_,is_legal_ml_type) + call mld_check_def(p%iprcparm(mld_aggr_alg_),'Aggregation',& + & mld_dec_aggr_,is_legal_ml_aggr_alg) + call mld_check_def(p%iprcparm(mld_aggr_kind_),'Smoother',& + & mld_smooth_prol_,is_legal_ml_aggr_kind) + call mld_check_def(p%iprcparm(mld_coarse_mat_),'Coarse matrix',& + & mld_distr_mat_,is_legal_ml_coarse_mat) + call mld_check_def(p%iprcparm(mld_smoother_pos_),'smooth_pos',& + & mld_pre_smooth_,is_legal_ml_smooth_pos) + call mld_check_def(p%iprcparm(mld_aggr_omega_alg_),'Omega Alg.',& + & mld_eig_est_,is_legal_ml_aggr_omega_alg) + call mld_check_def(p%iprcparm(mld_aggr_eig_),'Eigenvalue estimate',& + & mld_max_norm_,is_legal_ml_aggr_eig) + call mld_check_def(p%rprcparm(mld_aggr_omega_val_),'Omega',dzero,is_legal_omega) + call mld_check_def(p%rprcparm(mld_aggr_thresh_),'Aggr_Thresh',dzero,is_legal_aggr_thrs) + + + ! + ! Build a mapping between the row indices of the fine-level matrix + ! and the row indices of the coarse-level matrix, according to a decoupled + ! aggregation algorithm. This also defines a tentative prolongator from + ! the coarse to the fine level. + ! + call mld_aggrmap_bld(p%iprcparm(mld_aggr_alg_),p%rprcparm(mld_aggr_thresh_),& + & a,desc_a,p%nlaggr,p%mlia,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmap_bld') + goto 9999 + end if + + ! + ! Build the coarse-level matrix from the fine level one, starting from + ! the mapping defined by mld_aggrmap_bld and applying the aggregation + ! algorithm specified by p%iprcparm(mld_aggr_kind_) + ! + call mld_aggrmat_asb(a,desc_a,p,info) + if(info /= 0) then + call psb_errpush(4010,name,a_err='mld_aggrmat_asb') + goto 9999 + end if + ! + ! Fix the base_a and base_desc pointers for handling of residuals. + ! This is correct because this routine is only called at levels >=2. + ! + p%base_a => p%ac + p%base_desc => p%desc_ac + + call psb_erractionrestore(err_act) + return + +9999 continue + call psb_erractionrestore(err_act) + if (err_act.eq.psb_act_abort_) then + call psb_error() + return + end if + Return + +end subroutine mld_zaggr_bld