Changeset 26165 for issm/trunk-jpl/src/c/classes/FemModel.cpp
- Timestamp:
- 03/30/21 19:32:13 (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/classes/FemModel.cpp
r26114 r26165 4748 4748 /*}}}*/ 4749 4749 #endif 4750 #ifdef _HAVE_SEALEVELCHANGE_4751 void FemModel::SealevelchangeBarystatic(Vector<IssmDouble>* pRSLgi, IssmDouble* poceanarea, IssmDouble* pbslc,IssmDouble* pbslcice, IssmDouble* pbslchydro, IssmDouble** pbslcice_partition,IssmDouble** pbslchydro_partition,SealevelMasks* masks) { /*{{{*/4752 4753 /*serialized vectors:*/4754 IssmDouble bslcice = 0.;4755 IssmDouble bslcice_cpu = 0.;4756 IssmDouble bslchydro = 0.;4757 IssmDouble bslchydro_cpu = 0.;4758 IssmDouble area = 0.;4759 IssmDouble oceanarea = 0.;4760 IssmDouble oceanarea_cpu = 0.;4761 int bp_compute_fingerprints= 0;4762 bool isoceantransport=false;4763 4764 Vector<IssmDouble>* bslcice_partition=NULL;4765 IssmDouble* bslcice_partition_serial=NULL;4766 IssmDouble* partitionice=NULL;4767 int npartice,nel;4768 4769 Vector<IssmDouble>* bslchydro_partition=NULL;4770 IssmDouble* bslchydro_partition_serial=NULL;4771 IssmDouble* partitionhydro=NULL;4772 bool istws=0;4773 int nparthydro;4774 4775 int npartocean;4776 Vector<IssmDouble>* bslcocean_partition=NULL;4777 IssmDouble* bslcocean_partition_serial=NULL;4778 IssmDouble* partitionocean=NULL;4779 4780 /*Initialize temporary vector that will be used to sum barystatic components4781 * on all local elements, prior to assembly:*/4782 int gsize = this->nodes->NumberOfDofs(GsetEnum);4783 IssmDouble* RSLgi=xNewZeroInit<IssmDouble>(gsize);4784 int* indices=xNew<int>(gsize);4785 for(int i=0;i<gsize;i++) indices[i]=i;4786 4787 /*First, figure out the area of the ocean, which is needed to compute the barystatic component: */4788 int i = -1;4789 for(Object* & object : this->elements->objects){4790 i +=1;4791 Element* element = xDynamicCast<Element*>(object);4792 element->GetInputValue(&area,AreaEnum);4793 if (masks->isoceanin[i]) oceanarea_cpu += area;4794 }4795 ISSM_MPI_Reduce (&oceanarea_cpu,&oceanarea,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );4796 ISSM_MPI_Bcast(&oceanarea,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());4797 _assert_(oceanarea>0.);4798 4799 /*Initialize partition vectors to retrieve barystatic contributions: */4800 this->parameters->FindParam(&npartice,SolidearthNpartIceEnum);4801 if(npartice){4802 this->parameters->FindParam(&partitionice,&nel,NULL,SolidearthPartitionIceEnum);4803 bslcice_partition= new Vector<IssmDouble>(npartice);4804 }4805 4806 this->parameters->FindParam(&nparthydro,SolidearthNpartHydroEnum);4807 if(nparthydro){4808 this->parameters->FindParam(&partitionhydro,&nel,NULL,SolidearthPartitionHydroEnum);4809 bslchydro_partition= new Vector<IssmDouble>(nparthydro);4810 }4811 4812 this->parameters->FindParam(&npartocean,SolidearthNpartOceanEnum);4813 if(npartocean){4814 this->parameters->FindParam(&partitionocean,&nel,NULL,SolidearthPartitionOceanEnum);4815 bslchydro_partition= new Vector<IssmDouble>(npartocean);4816 }4817 /*For later:4818 npartbarystatic=npartice;4819 if(nparthydro>npartbarystatic)npartbarystatic=nparthydro;4820 if(npartocean>npartbarystatic)npartbarystatic=npartocean;4821 bslc_partition=new Matrix(IssmDouble>(npartbarystatic,3);4822 4823 bslc_cpu[0]=0; bslc_cpu[1]=0; bslc_cpu[2]=0;4824 for(Object* & object : this->elements->objects){4825 Element* element = xDynamicCast<Element*>(object);4826 element->SealevelchangeBarystaticLoads(&bslc_cpu[0], localloads,masks, bslcice_partition,partitionice,oceanarea);4827 }4828 MPI Bcast localloads -> loads4829 4830 for(Object* & object : this->elements->objects){4831 Element* element = xDynamicCast<Element*>(object);4832 element->SealevelchangeConvolution(loads);4833 }4834 */4835 4836 4837 4838 4839 4840 /*Call the barystatic sea level change core for ice : */4841 bslcice_cpu=0;4842 for(Object* & object : this->elements->objects){4843 Element* element = xDynamicCast<Element*>(object);4844 bslcice_cpu+=element->SealevelchangeBarystaticIce(RSLgi,masks, bslcice_partition,partitionice,oceanarea);4845 }4846 4847 /*Call the barystatic sea level change core for hydro: */4848 bslchydro_cpu=0; //make sure to initialize this, so we have a total barystatic contribution computed at 0.4849 this->parameters->FindParam(&istws,TransientIshydrologyEnum);4850 if(istws){4851 for(int i=0;i<elements->Size();i++){4852 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i));4853 bslchydro_cpu+=element->SealevelchangeBarystaticHydro(RSLgi,masks, bslchydro_partition,partitionhydro,oceanarea);4854 }4855 }4856 4857 /*Call the barystatic sea level change core for bottom pressures: */4858 this->parameters->FindParam(&bp_compute_fingerprints,SolidearthSettingsComputeBpGrdEnum);4859 this->parameters->FindParam(&isoceantransport,TransientIsoceantransportEnum);4860 if(bp_compute_fingerprints && isoceantransport){4861 for(int i=0;i<elements->Size();i++){4862 Element* element=xDynamicCast<Element*>(elements->GetObjectByOffset(i));4863 element->SealevelchangeBarystaticBottomPressure(RSLgi,masks);4864 }4865 }4866 4867 /*Plug values once and assemble: */4868 pRSLgi->SetValues(gsize,indices,RSLgi,ADD_VAL);4869 pRSLgi->Assemble();4870 4871 /*Sum all barystatic components from all cpus:*/4872 ISSM_MPI_Reduce (&bslcice_cpu,&bslcice,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );4873 ISSM_MPI_Bcast(&bslcice,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());4874 _assert_(!xIsNan<IssmDouble>(bslcice));4875 4876 ISSM_MPI_Reduce (&bslchydro_cpu,&bslchydro,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );4877 ISSM_MPI_Bcast(&bslchydro,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());4878 _assert_(!xIsNan<IssmDouble>(bslchydro));4879 4880 /*Take care of partition vectors:*/4881 if(bslcice_partition){4882 bslcice_partition->Assemble();4883 bslcice_partition_serial=bslcice_partition->ToMPISerial();4884 }4885 if(bslchydro_partition){4886 bslchydro_partition->Assemble();4887 bslchydro_partition_serial=bslchydro_partition->ToMPISerial();4888 }4889 4890 4891 /*Free ressources:*/4892 xDelete<int>(indices);4893 xDelete<IssmDouble>(RSLgi);4894 if(bslchydro_partition)delete bslchydro_partition;4895 if(bslcice_partition)delete bslcice_partition;4896 if(partitionhydro)xDelete<IssmDouble>(partitionhydro);4897 if(partitionice)xDelete<IssmDouble>(partitionice);4898 4899 /*Assign output pointers:*/4900 *poceanarea = oceanarea;4901 *pbslcice = bslcice;4902 *pbslchydro = bslchydro;4903 *pbslc=bslchydro+bslcice;4904 *pbslcice_partition=bslcice_partition_serial;4905 *pbslchydro_partition=bslchydro_partition_serial;4906 4907 }4908 /*}}}*/4909 void FemModel::SealevelchangeSal(Vector<IssmDouble>* pRSLgo, Vector<IssmDouble>* pRSLg_old, SealevelMasks* masks, bool verboseconvolution){/*{{{*/4910 4911 /*serialized vectors:*/4912 IssmDouble* RSLg_old=NULL;4913 4914 IssmDouble* RSLgo = NULL;4915 int* indices = NULL;4916 int gsize;4917 4918 bool computerigid = true;4919 bool computeelastic= true;4920 4921 /*recover computational flags: */4922 this->parameters->FindParam(&computerigid,SolidearthSettingsRigidEnum);4923 4924 /*Initialize temporary vector that will be used to sum barystatic components on all local elements, prior4925 * to assembly:*/4926 gsize = this->nodes->NumberOfDofs(GsetEnum);4927 RSLgo=xNewZeroInit<IssmDouble>(gsize);4928 indices=xNew<int>(gsize); for (int i=0;i<gsize;i++)indices[i]=i;4929 4930 /*Serialize vectors from previous iteration:*/4931 RSLg_old=pRSLg_old->ToMPISerial();4932 4933 /*Call the sal sea level change core only if required: */4934 if(computerigid){4935 for(Object* & object : this->elements->objects){4936 Element* element = xDynamicCast<Element*>(object);4937 element->SealevelchangeSal(RSLgo,RSLg_old,masks);4938 }4939 }4940 pRSLgo->SetValues(gsize,indices,RSLgo,ADD_VAL);4941 pRSLgo->Assemble();4942 4943 /*Free ressources:*/4944 xDelete<int>(indices);4945 xDelete<IssmDouble>(RSLgo);4946 xDelete<IssmDouble>(RSLg_old);4947 4948 }4949 /*}}}*/4950 void FemModel::SealevelchangeRotationalFeedback(Vector<IssmDouble>* pRSLgo_rot, Vector<IssmDouble>* pRSLg_old, IssmDouble* pIxz, IssmDouble* pIyz, IssmDouble* pIzz, SealevelMasks* masks){/*{{{*/4951 4952 /*serialized vectors:*/4953 bool spherical=true;4954 IssmDouble* RSLg_old=NULL;4955 IssmDouble* tide_love_h = NULL;4956 IssmDouble* tide_love_k = NULL;4957 IssmDouble* load_love_k = NULL;4958 IssmDouble tide_love_k2secular;4959 IssmDouble moi_e, moi_p, omega, g;4960 IssmDouble m1, m2, m3;4961 IssmDouble lati, longi, radi, value;4962 IssmDouble *latitude = NULL;4963 IssmDouble *longitude = NULL;4964 IssmDouble *radius = NULL;4965 4966 /*Serialize vectors from previous iteration:*/4967 RSLg_old=pRSLg_old->ToMPISerial();4968 4969 IssmDouble moi_list[3]={0,0,0};4970 IssmDouble moi_list_cpu[3]={0,0,0};4971 for(Object* & object : this->elements->objects){4972 Element* element = xDynamicCast<Element*>(object);4973 element->SealevelchangeMomentOfInertia(&moi_list[0],RSLg_old,masks );4974 moi_list_cpu[0] += moi_list[0];4975 moi_list_cpu[1] += moi_list[1];4976 moi_list_cpu[2] += moi_list[2];4977 }4978 ISSM_MPI_Reduce (&moi_list_cpu[0],&moi_list[0],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );4979 ISSM_MPI_Bcast(&moi_list[0],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());4980 //4981 ISSM_MPI_Reduce (&moi_list_cpu[1],&moi_list[1],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );4982 ISSM_MPI_Bcast(&moi_list[1],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());4983 //4984 ISSM_MPI_Reduce (&moi_list_cpu[2],&moi_list[2],1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );4985 ISSM_MPI_Bcast(&moi_list[2],1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());4986 4987 /*pull out some useful parameters: */4988 parameters->FindParam(&load_love_k,NULL,NULL,LoadLoveKEnum);4989 parameters->FindParam(&tide_love_h,NULL,NULL,TidalLoveHEnum);4990 parameters->FindParam(&tide_love_k,NULL,NULL,TidalLoveKEnum);4991 parameters->FindParam(&tide_love_k2secular,TidalLoveK2SecularEnum);4992 parameters->FindParam(&moi_e,RotationalEquatorialMoiEnum);4993 parameters->FindParam(&moi_p,RotationalPolarMoiEnum);4994 parameters->FindParam(&omega,RotationalAngularVelocityEnum);4995 4996 /*compute perturbation terms for angular velocity vector: */4997 m1 = 1/(1-tide_love_k[2]/tide_love_k2secular) * (1+load_love_k[2])/(moi_p-moi_e) * moi_list[0];4998 m2 = 1/(1-tide_love_k[2]/tide_love_k2secular) * (1+load_love_k[2])/(moi_p-moi_e) * moi_list[1];4999 m3 = -(1+load_love_k[2])/moi_p * moi_list[2]; // term associated with fluid number (3-order-of-magnitude smaller) is negelected5000 5001 /*recover lat,long and radius vectors from vertices: */5002 VertexCoordinatesx(&latitude,&longitude,&radius,this->vertices,spherical);5003 5004 /* Green's function (1+k_2-h_2/g): checked against Glenn Milne's thesis Chapter 3 (eqs: 3.3-4, 3.10-11)5005 * Perturbation terms for angular velocity vector (m1, m2, m3): checked against Mitrovica (2005 Appendix) & Jensen et al (2013 Appendix A3)5006 * Sea level rotational feedback: checked against GMD eqs 8-9 (only first order terms, i.e., degree 2 order 0 & 1 considered)5007 * all DONE in Geographic coordinates: theta \in [-90,90], lambda \in [-180 180]5008 */5009 for(Object* & object : vertices->objects){5010 Vertex* vertex=xDynamicCast<Vertex*>(object);5011 int sid=vertex->Sid();5012 5013 lati=latitude[sid]/180*PI;5014 longi=longitude[sid]/180*PI;5015 radi=radius[sid];5016 5017 /*only first order terms are considered now: */5018 value=((1.0+tide_love_k[2]-tide_love_h[2])/9.81)*pow(omega*radi,2.0)*5019 (-m3/6.0 + 0.5*m3*cos(2.0*lati) - 0.5*sin(2.*lati)*(m1*cos(longi)+m2*sin(longi)));5020 5021 pRSLgo_rot->SetValue(sid,value,INS_VAL); //INS_VAL ensures that you don't add several times5022 }5023 5024 /*Assemble mesh velocity*/5025 pRSLgo_rot->Assemble();5026 5027 /*Assign output pointers:*/5028 if(pIxz)*pIxz=moi_list[0];5029 if(pIyz)*pIyz=moi_list[1];5030 if(pIzz)*pIzz=moi_list[2];5031 xDelete<IssmDouble>(latitude);5032 xDelete<IssmDouble>(longitude);5033 xDelete<IssmDouble>(tide_love_h);5034 xDelete<IssmDouble>(tide_love_k);5035 xDelete<IssmDouble>(load_love_k);5036 5037 xDelete<IssmDouble>(radius);5038 5039 /*Free ressources:*/5040 xDelete<IssmDouble>(RSLg_old);5041 5042 }5043 /*}}}*/5044 void FemModel::SealevelchangeDeformation(Vector<IssmDouble>* pgeoid, Vector<IssmDouble>* pUp, Vector<IssmDouble>* pNorth, Vector<IssmDouble>* pEast, Vector<IssmDouble>* pRSLg, SealevelMasks* masks){/*{{{*/5045 5046 /*serialized vectors:*/5047 IssmDouble* RSLg=NULL;5048 5049 IssmDouble* Up = NULL;5050 IssmDouble* North = NULL;5051 IssmDouble* East = NULL;5052 int* indices = NULL;5053 int gsize;5054 int horiz;5055 5056 /*retrieve parameters:*/5057 this->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum);5058 5059 /*Serialize vectors from previous iteration:*/5060 RSLg=pRSLg->ToMPISerial();5061 5062 /*Initialize temporary vector that will be used to sum barystatic components on all local elements, prior5063 * to assembly:*/5064 gsize = this->nodes->NumberOfDofs(GsetEnum);5065 Up=xNewZeroInit<IssmDouble>(gsize);5066 if(horiz){5067 North=xNewZeroInit<IssmDouble>(gsize);5068 East=xNewZeroInit<IssmDouble>(gsize);5069 }5070 indices=xNew<int>(gsize); for (int i=0;i<gsize;i++)indices[i]=i;5071 5072 /*Call the deformation from loading routines:*/5073 for(Object* & object : this->elements->objects){5074 Element* element = xDynamicCast<Element*>(object);5075 element->DeformationFromSurfaceLoads(Up,North,East,RSLg,masks);5076 }5077 5078 pUp->SetValues(gsize,indices,Up,ADD_VAL);5079 pUp->Assemble();5080 5081 5082 /*Add RSL to Up to find the geoid: */5083 pUp->Copy(pgeoid); pgeoid->AXPY(pRSLg,1);5084 5085 if (horiz){5086 pNorth->SetValues(gsize,indices,North,ADD_VAL);5087 pNorth->Assemble();5088 pEast->SetValues(gsize,indices,East,ADD_VAL);5089 pEast->Assemble();5090 }5091 5092 /*Free ressources:*/5093 xDelete<IssmDouble>(Up);5094 if(horiz){5095 xDelete<IssmDouble>(North);5096 xDelete<IssmDouble>(East);5097 }5098 xDelete<int>(indices);5099 xDelete<IssmDouble>(RSLg);5100 }5101 /*}}}*/5102 IssmDouble FemModel::SealevelchangeOceanAverage(Vector<IssmDouble>* RSLg,SealevelMasks* masks, IssmDouble oceanarea) { /*{{{*/5103 5104 IssmDouble* RSLg_serial=NULL;5105 IssmDouble oceanvalue,oceanvalue_cpu;5106 5107 /*Serialize vectors from previous iteration:*/5108 RSLg_serial=RSLg->ToMPISerial();5109 5110 /*Initialize:*/5111 oceanvalue_cpu=0;5112 5113 /*Go through elements, and add contribution from each element and divide by overall ocean area:*/5114 for(Object* & object : this->elements->objects){5115 Element* element = xDynamicCast<Element*>(object);5116 oceanvalue_cpu += element->OceanAverage(RSLg_serial,masks);5117 }5118 5119 ISSM_MPI_Reduce (&oceanvalue_cpu,&oceanvalue,1,ISSM_MPI_DOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm() );5120 ISSM_MPI_Bcast(&oceanvalue,1,ISSM_MPI_DOUBLE,0,IssmComm::GetComm());5121 5122 /*Free ressources:*/5123 xDelete<IssmDouble>(RSLg_serial);5124 5125 return oceanvalue/oceanarea;5126 }5127 /*}}}*/5128 void FemModel::IvinsDeformation(Vector<IssmDouble>* wg,Vector<IssmDouble>* dwgdt, IssmDouble* x, IssmDouble* y){ /*{{{*/5129 5130 /*Find the litho material to be used by all the elements:*/5131 Matlitho* matlitho=NULL;5132 for (Object* & object: this->materials->objects){5133 Material* material=xDynamicCast<Material*>(object);5134 if(material->ObjectEnum()==MatlithoEnum){5135 matlitho=xDynamicCast<Matlitho*>(material);5136 break;5137 }5138 }5139 _assert_(matlitho);5140 5141 5142 /*Go through elements, and add contribution from each element to the deflection vector wg:*/5143 for(Object* & object : this->elements->objects){5144 Element* element = xDynamicCast<Element*>(object);5145 element->GiaDeflection(wg,dwgdt, matlitho, x,y);5146 }5147 5148 /*Assemble parallel vector:*/5149 dwgdt->Assemble();5150 wg->Assemble();5151 }5152 /*}}}*/5153 #endif5154 4750 void FemModel::HydrologyEPLupdateDomainx(IssmDouble* pEplcount){ /*{{{*/ 5155 4751
Note:
See TracChangeset
for help on using the changeset viewer.